var consoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);


var theInstance = _newInstance();

var Module = {
   

  //firstTime: true,

    registerSelf: function (compMgr, fileSpec, location, type) {
    //if (this.firstTime) {
    //        dump("*** Deferring registration of URL Poster JS components\n");
    //        this.firstTime = false;
    //        throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
    //    }
        debug("*** Registering sample JS components\n");
        compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
        compMgr.registerFactoryLocation(this.myCID,
                                        "Atomic Atom Client Component",
                                        this.myProgID,
                                        fileSpec,
                                        location,
                                        type);
    },

    getClassObject : function (compMgr, cid, iid) {
       //consoleService.logStringMessage("Getting class for "+cid);
    
       if (cid.equals(this.myCID)) {
          return this.myFactory;
       }
       if (!iid.equals(Components.interfaces.nsIFactory)) {
          throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
       }
       throw Components.results.NS_ERROR_NO_INTERFACE;
    },

    myCID: Components.ID("{fc654c0a-b21a-4321-b563-bd9b2bd96bf0}"),
    myProgID: "@milowski.com/atomic;1",

    myFactory: {
        getService: function(outer,iid) {
           dump("CI: " + iid + "\n");
           if (outer != null) {
              throw Components.results.NS_ERROR_NO_AGGREGATION;
	   }
	   return theInstance.QueryInterface(iid);
        },
        createInstance: function (outer, iid) {
            dump("CI: " + iid + "\n");
            if (outer != null) {
               throw Components.results.NS_ERROR_NO_AGGREGATION;
	    }
            return _newInstance().QueryInterface(iid);
        }
    },

    canUnload: function(compMgr) {
        dump("****** Unloading: Atomic JS component! ****** \n");
        return true;
    }
}; // END Module

function _newInstance() {
   return new AtomicService();
}

function AtomicService() {
   this.wrappedJSObject = this;
   this.services = {};
   this.plugins = {};
   this.pluginsLoaded = false;
   this.loaded = false;
   try {
      this.config = new AtomicConfig();
   } catch (e){
      consoleService.logStringMessage(e);
   }
}

AtomicService.prototype.getAtomService = function(url,source) {
   var service = this.services[url];
   if (!service) {
      service = new AtomService(url,source);
      this.services[url] = service;
   }
   return service;
}

AtomicService.prototype.loadPlugins = function() {
   var current = this;
   HTTP("GET","chrome://atomic/content/plugins/catalog.xml",{
      synchronizedRequest: true,
      onSuccess: function(status,document) {
         current._loadPlugins(document.documentElement);
         current.pluginsLoaded = true;
      },
      onFailure: function(status,document) {
         consoleService.logStringMessage("Cannot load plugin catalog.");
      }
   });
}

AtomicService.prototype._loadPlugins = function(catalog) {
   var links = catalog.getElementsByTagNameNS(ATOMIC_PLUGIN_NS,"link")
   var baseURI = _ioService.newURI(catalog.baseURI,null,null);
   for (var i=0; i<links.length; i++) {
      var link = links[i];
      var href = link.getAttribute("href");
      var url = _ioService.newURI(href,null,baseURI).spec;
      var currentApp = this;
      HTTP("GET",url,{
         onSuccess: function(status,doc) {
            if (doc.documentElement) {
               currentApp.loadPlugin(doc.documentElement);
            } else {
               consoleService.logStringMessage("No document returned for plugin document "+url);
            }
         },
         onFailure: function(status,document) {
            consoleService.logStringMessage("Cannot load plugin from "+url+", status="+status);
         }
      });
   }
}
AtomicService.prototype.loadPlugin = function(manifest) {
   if (!manifest) {
      return;
   }
   var p = new Plugin();
   try {
      p.load(manifest);
      this.plugins[p.id] = p;
   } catch (ex) {
      consoleService.logStringMessage("ERROR: "+ex);
   }
}

AtomicService.prototype.loadServices = function() {
   var nl = this.config.document.getElementsByTagNameNS(ATOMIC_CONFIG_NS,"services")
   if (nl.length==0) {
      nl = this.config.document.getElementsByTagNameNS(ATOMIC_OLD_CONFIG_NS,"services");
   }
   if (nl.length==0) {
      throw "Cannot find {"+ATOMIC_CONFIG_NS+"}services element in "+this.config.configURL;
   }
   var servicesE = nl.item(0);
   var child = servicesE.firstChild;
   while (child) {
      if (child.nodeType==1) {
         if (child.namespaceURI==ATOMIC_CONFIG_NS || child.namespaceURI==ATOMIC_OLD_CONFIG_NS) {
            if (child.localName=="link") {
               if (child.getAttribute("type")==ATOM_PUB_INTROSPECT_MIME_TYPE) {
                  var url = child.getAttribute("href");
                  var service = this.getAtomService(url,child);
                  var rel = child.getAttribute("rel");
                  if (rel && rel.indexOf("google")>=0) {
                     service.google = true;
                  }
                  service.title = child.getAttribute("title");
                  service.author = child.getAttribute("author");
                  service.username = child.getAttribute("username");
                  service.password = child.getAttribute("password");
                  if (!service.author) {
                     service.author = service.username;
                  }
               }
            }
         } else if (child.namespaceURI==ATOM_PUB_INTROSPECT_NS) {
            if (child.localName=="service") {
               var url = child.getAttribute("xml:base");
               var service = this.getAtomService(url,child);
               var rel = child.getAttribute("rel");
               if (rel && (rel.indexOf("blogspot")>=0 || rel.indexOf("google")>=0)) {
                  service.google = true;
               }
               service.title = child.getAttribute("title");
               service.author = child.getAttribute("author");
               service.username = child.getAttribute("username");
               service.password = child.getAttribute("password");
               if (!service.author) {
                  service.author = service.username;
               }
               service.loadIntrospection(child);
            }
         }
      }
      child = child.nextSibling;
   }
}

AtomicService.prototype.googleClientLogin = function(username,password,options) {
   var loginBody = "service=blogger&Email="+username+"&Passwd="+password;
   HTTP("POST","https://www.google.com/accounts/ClientLogin",{
      timeout: options.timeout,
      contentType: "application/x-www-form-urlencoded",
      onSuccess: function(status,doc,text) {
         var regex = /Auth=.+/;
         var match = regex.exec(text);
         var auth=match[0].substring(5);
         options.onSuccess(auth);
      },
      onFailure: options.onFailure,
      body: loginBody
   });
}

AtomicService.prototype.QueryInterface = function(iid) {
    /*
     *  This code specifies that the component supports 1 interfaces:
     *  nsISupports.
     */
    if (!iid.equals(Components.interfaces.nsISupports)) {
        throw Components.results.NS_ERROR_NO_INTERFACE;
    }
    return this;
};


function NSGetModule(compMgr, fileSpec) { return Module; }
